package com.xh.bussiness.permission.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xh.bussiness.permission.model.User;
import com.xh.bussiness.permission.service.IUserOnlineService;
import com.xh.bussiness.permission.service.IUserService;
import com.xh.bussiness.system.constant.UserOnlineConstant;
import com.xh.core.util.CacheUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class UserOnlineServiceImpl implements IUserOnlineService {

    @Autowired
    private IUserService userService;

    // 更新用户在线状态
    @Override
    public void updateOnlineStates() {
        // 初始化 准备更新缓存用的
        List<String> prepareUpdate = new ArrayList<>();
        // 在线用户缓存
        List<String> userIds = onlineCache();
        // 对缓存进行遍历
        for (String userId : userIds) {
            int newState = newUserOnlineState(userId);
            // 在线状态发生改变的
            if(UserOnlineConstant.OFFLINE == newState) {
                // 添加到 prepareUpdate
                prepareUpdate.add(userId);
            }
        }
        // 更新数据库在线状态
        updateOnlineStates(prepareUpdate, UserOnlineConstant.OFFLINE);
        // 更新在线用户缓存
        removeOnlineCache(prepareUpdate);
    }

    // 更新用户最后一次请求的标识
    @Override
    public boolean updateLastRquest(String userId, boolean withDB) {
        // 如果缓存不存在
        if(UserOnlineConstant.OFFLINE == newUserOnlineState(userId)) {
            if(withDB) {
                // 更新数据库在线状态
                updateOnlineStates(Collections.singletonList(userId), UserOnlineConstant.ONLINE);
            }
            // 更新在线用户缓存
            addOnlineCache(userId);
        }
        // 延长缓存时间
        return CacheUtils.set(UserOnlineConstant.USER_LAST_RQUEST_KEY_PREFIX + userId, userId);
    }

    // 用户最新的在线状态
    @Override
    public int newUserOnlineState(String userId) {
        // 用户最后一次请求的标识 如果不存在则为离线
        if(null == CacheUtils.get(UserOnlineConstant.USER_LAST_RQUEST_KEY_PREFIX + userId)) {
            return UserOnlineConstant.OFFLINE;
        }
        return UserOnlineConstant.ONLINE;
    }

    // 更新数据库在线状态
    private boolean updateOnlineStates(List<String> userIds, int online) {
        if(userIds.isEmpty()) {
            return true;
        }
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.in("id", userIds);
        List<User> users = userService.selectList(qw, User.class);
        for (User user : users) {
            user.setOnline(online);
        }
        return userService.batchUpdate(users);
    }

    // 在线用户缓存
    private List<String> onlineCache() {
        Object o = CacheUtils.get(UserOnlineConstant.USER_ONLINE_IDS_KEY);
        if(null != o) {
            return JSON.parseObject(String.valueOf(o), new TypeReference<List<String>>(){});
        }
        return new ArrayList<>();
    }

    // 更新在线用户缓存
    private void removeOnlineCache(List<String> userIds) {
        if(userIds.isEmpty()) {
            return;
        }
        long version = onlineCacheVersion();
        // 获取最新的缓存
        List<String> prepareUpdate = onlineCache().stream().filter(userId -> !userIds.contains(userId)).collect(Collectors.toList());
        if(prepareUpdate.isEmpty()) {
            return;
        }
        if(version == onlineCacheVersion()) {
            // 更新缓存
            CacheUtils.set(UserOnlineConstant.USER_ONLINE_IDS_KEY, JSON.toJSONString(prepareUpdate));
            deleteOnlineCacheVersion();
        } else {
            removeOnlineCache(userIds);
        }
    }

    // 更新在线用户缓存
    private void addOnlineCache(String userId) {
        long version = onlineCacheVersion();
        // 获取最新的缓存
        List<String> prepareUpdate = Stream.of(onlineCache(), Collections.singletonList(userId)).flatMap(Collection::stream).distinct().collect(Collectors.toList());
        if(prepareUpdate.isEmpty()) {
            return;
        }
        if(version == onlineCacheVersion()) {
            // 更新缓存
            CacheUtils.set(UserOnlineConstant.USER_ONLINE_IDS_KEY, JSON.toJSONString(prepareUpdate));
            deleteOnlineCacheVersion();
        } else {
            addOnlineCache(userId);
        }
    }

    // 在线用户版本号
    private long onlineCacheVersion() {
        Object version = CacheUtils.get(UserOnlineConstant.USER_ONLINE_IDS_VERSION_KEY);
        if(null != version) {
            return Long.parseLong(String.valueOf(version));
        }
        long now = System.currentTimeMillis();
        CacheUtils.set(UserOnlineConstant.USER_ONLINE_IDS_VERSION_KEY, now);
        return now;
    }

    // 更新在线用户版本号
    private void deleteOnlineCacheVersion() {
        CacheUtils.delete(UserOnlineConstant.USER_ONLINE_IDS_VERSION_KEY);
    }
}
